/**
 * @file hal_sec_hash.c
 * @brief 
 * 
 * Copyright 2019-2030 Bouffalolab team
 * 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 * 
 */
#include "hal_sec_hash.h"
#include "bl702_sec_eng.h"

void SEC_SHA_IRQHandler(void);

static sec_hash_device_t sec_hashx_device[SEC_HASH_MAX_INDEX] =
{
    0
};
static SEC_Eng_SHA256_Ctx shaCtx;
/**
 * @brief 
 * 
 * @param dev 
 * @param oflag 
 * @return int 
 */
int sec_hash_open(struct device *dev, uint16_t oflag)
{
    sec_hash_device_t *sec_hash_device = (sec_hash_device_t *)dev;
    int ret=0;

    switch(sec_hash_device->type)
    {
        case SEC_HASH_SHA1 :
        	ret=-1;
            break;
        case SEC_HASH_SHA224:
            Sec_Eng_SHA256_Init(&shaCtx,SEC_ENG_SHA_ID0,SEC_ENG_SHA224,sec_hash_device->shaBuf,sec_hash_device->shaPadding);
            Sec_Eng_SHA_Start(SEC_ENG_SHA_ID0);
            break;
        case SEC_HASH_SHA256 :
            Sec_Eng_SHA256_Init(&shaCtx,SEC_ENG_SHA_ID0,SEC_ENG_SHA256,sec_hash_device->shaBuf,sec_hash_device->shaPadding);
            Sec_Eng_SHA_Start(SEC_ENG_SHA_ID0);
            break;
        case SEC_HASH_SHA384:
        case SEC_HASH_SHA512:
        	ret=-1;
            break;
        default:
            ret=-1;
            break;            
    }
    return ret;
}
/**
 * @brief 
 * 
 * @param dev 
 * @return int 
 */
int sec_hash_close(struct device *dev)
{
    sec_hash_device_t *sec_hash_device = (sec_hash_device_t *)dev;
    memset(sec_hash_device,0,sizeof(sec_hash_device_t));

    return 0;
}
/**
 * @brief 
 * 
 * @param dev 
 * @param cmd 
 * @param args 
 * @return int 
 */
int sec_hash_control(struct device *dev, int cmd, void *args)
{

    return 0;
}

/**
 * @brief 
 * 
 * @param dev 
 * @param pos 
 * @param buffer 
 * @param size 
 * @return int 
 */
int sec_hash_write(struct device *dev, uint32_t pos, const void *buffer, uint32_t size)
{
    sec_hash_device_t *sec_hash_device = (sec_hash_device_t *)dev;
    int ret = 0;

    switch(sec_hash_device->type)
    {
        case SEC_HASH_SHA1 :
        	ret=-1;
            break;
        case SEC_HASH_SHA224:
            Sec_Eng_SHA256_Update(&shaCtx,SEC_ENG_SHA_ID0,(uint8_t*)buffer, size);
            break;
        case SEC_HASH_SHA256 :
            Sec_Eng_SHA256_Update(&shaCtx,SEC_ENG_SHA_ID0,(uint8_t*)buffer, size);
            break;
        case SEC_HASH_SHA384:
        case SEC_HASH_SHA512:
        	ret=-1;
            break;
        default:
            ret=-1;
            break;            
    }
    return ret;
}

/**
 * @brief 
 * 
 * @param dev 
 * @param pos 
 * @param buffer 
 * @param size 
 * @return int 
 */
int sec_hash_read(struct device *dev, uint32_t pos, void *buffer, uint32_t size)
{
    sec_hash_device_t *sec_hash_device = (sec_hash_device_t *)dev;
    int ret = 0;

    switch(sec_hash_device->type)
    {
        case SEC_HASH_SHA1 :
        	ret=-1;
            break;
        case SEC_HASH_SHA224:
            Sec_Eng_SHA256_Finish(&shaCtx,SEC_ENG_SHA_ID0,(uint8_t *)buffer);
            ret=28;
            break;
        case SEC_HASH_SHA256 :
            Sec_Eng_SHA256_Finish(&shaCtx,SEC_ENG_SHA_ID0,(uint8_t *)buffer);
            ret=32;
            break;
        case SEC_HASH_SHA384:
        case SEC_HASH_SHA512:
        	ret=-1;
            break;
        default:
            ret=-1;
            break;            
    }
    return ret;
}

/**
 * @brief 
 * 
 * @param index 
 * @param type 
 * @param name 
 * @param flag 
 * @return int 
 */
static int sec_hash_sha_register(enum sec_hash_index_type index, enum sec_hash_type type,const char *name, uint16_t flag)
{
    struct device *dev;

    if(SEC_HASH_MAX_INDEX == 0)
    return -DEVICE_EINVAL;

    dev = &(sec_hashx_device[index].parent);
    sec_hashx_device[index].type=type;

    dev->open = sec_hash_open;
    dev->close = sec_hash_close;
    dev->control = sec_hash_control;
    dev->write = sec_hash_write;
    dev->read = sec_hash_read;

    dev->status = DEVICE_UNREGISTER;
    dev->type = DEVICE_CLASS_SEC_HASH;
    dev->handle = NULL;

    return device_register(dev, name, flag);
}

/**
 * @brief 
 * 
 * @param index 
 * @param name 
 * @param flag 
 * @return int 
 */
int sec_hash_sha256_register(enum sec_hash_index_type index, const char *name, uint16_t flag)
{
    return sec_hash_sha_register(index,SEC_HASH_SHA256, name, flag);
}

/**
 * @brief 
 * 
 * @param index 
 * @param name 
 * @param flag 
 * @return int 
 */
int sec_hash_sha224_register(enum sec_hash_index_type index, const char *name, uint16_t flag)
{
    return sec_hash_sha_register(index,SEC_HASH_SHA224, name, flag);
}

/**
 * @brief 
 * 
 * @param handle 
 */
void sec_hash_isr(sec_hash_device_t *handle)
{
}

/**
 * @brief 
 * 
 */
void SEC_SHA_IRQ(void)
{
    sec_hash_isr(&sec_hashx_device[0]);
}